#ifndef URL_H
#define URL_H
#include <QString>
#include <QRegExp>
#include <QVector>
#include "urlnode.h"
#include "sh_global.h"

/**
 * @brief The Url class
 * Works with all kind of url's in system
 * lc/dj/lamp=0
 * lc/dj/string=anything
 * lc/dj/key()
 * lc/dj/key(123, 'str' ', [arr])
 * lc/[group of dev's]/
 * lc/[group]()
 * lc/.../[group] will be implemented
 */
class SHSHARED_EXPORT Url
{
public:
    /**
     * @brief The ActionType enum
     * PROPERTY - smth.property_name
     * FUNCTION - exec a function
     */
    enum ArgumentType {PROPERTY, FUNCTION};
    /**
     * @brief Url
     * Invalid url
     */
    Url();
    /**
     * @brief Url
     * @param fromString string with url
     * @param syntaxCheck if false syntax won't be checked
     * Construct's url from string like this:
     * some_net.{net with this desc's}.[net with this group].device.func(args)
     * regexp's are supported everywhere
     */
    Url(const QString &urlString);
    /**
     * @brief Url construct from vector of nodes and current index
     * @param nodes
     * @param currentNodeIdx
     */
    Url(const QVector<UrlNode> &nodes,
        ArgumentType argumentType, const QVariant &argumentData,
        int currentNodeIdx = 0);
    /**
     * @brief isValid
     * @return true if url is valid (invalid after default constructor or bad string)
     */
    bool isValid() const;
    /**
     * @brief isTargetNet
     * @return true if current net is latest (device)
     * qwe/rty/uio/device/func()
     */
    bool isTargetNet() const;
    /**
     * @brief next move to next node
     * @return false if target node
     */
    bool next() const;
    /**
     * @brief currentNode
     * @return Current node or invalid node
     */
    UrlNode currentNode() const;
    /**
     * @brief currentNodeIdx
     * @return index of a current node
     */
    int currentNodeIdx() const;
    /**
     * @brief node
     * @param index
     * @return node with given index
     */
    UrlNode node(int index) const;
    /**
     * @brief nodesCount
     * @return
     */
    int nodesCount() const;
    /**
     * @brief nodes
     * @return all nodes as QVector
     */
    QVector<UrlNode> nodes() const;
    /**
     * @brief prepend insert node to begining
     * @param node
     */
    void prepend(UrlNode node);
    /**
     * @brief append insert node to the end
     * @param node
     */
    void append(UrlNode node);
    /**
     * @brief match
     * @param other
     * @param untillNode -1 all nodes
     * @return
     * this: qwe>rty>*
     * mathes: qwe>rty>asd
     */
    bool match(const Url &other, int untillNode = -1) const;
    /**
     * @brief toString
     * @return human readable string (note: this string can't be parsed with Url later!)
     */
    QString toString() const;
    /**
     * @brief argumentType what this url do: PROPERTY - set property, FUNCTION call function
     * @return
     */
    ArgumentType argumentType() const;
    /**
     * @brief argumentData property value or function arguments
     * @return
     */
    QVariant argumentData() const;
    /**
     * @brief setArgumentType will be removed? no need in this
     * @param type
     */
    void setArgumentType(ArgumentType type);
    /**
     * @brief setArgumentData set property value or function arguments
     * @param data
     */
    void setArgumentData(const QVariant &data);
private:
//    static QRegExp m_urlRx;
    QVector<UrlNode> m_nodes;
    mutable int m_curNode;
    // (arguments)
    QVariantList parse_args(const QString &args) const;
    static QRegExp m_argsRx;
    QVariant m_argumentData;
    ArgumentType m_argumentType;
};

QDataStream SHSHARED_EXPORT &operator<<(QDataStream &out, const Url &url);
QDataStream SHSHARED_EXPORT &operator>>(QDataStream &in, Url &url);
#endif // URL_H
